home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / tprim.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  20KB  |  864 lines

  1. /*
  2.  * (c) Copyright 1993-94, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software for
  6.  * any purpose and without fee is hereby granted, provided that the above
  7.  * copyright notice appear in all copies and that both the copyright notice
  8.  * and this permission notice appear in supporting documentation, and that
  9.  * the name of Silicon Graphics, Inc. not be used in advertising
  10.  * or publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.
  12.  *
  13.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  14.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  15.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  16.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  17.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  18.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  19.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  20.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  21.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  22.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  23.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  24.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
  27.  * Use, duplication, or disclosure by the Government is subject to
  28.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  29.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  30.  * clause at DFARS 252.227-7013 and/or in similar or successor
  31.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  32.  * Unpublished-- rights reserved under the copyright laws of the
  33.  * United States.  Contractor/manufacturer is Silicon Graphics,
  34.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  35.  *
  36.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  37.  */
  38. #include <GL/glx.h>
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <unistd.h>
  42. #include <stdlib.h>
  43. #include <X11/keysym.h>
  44. #include <math.h>
  45. #include <sys/types.h>
  46. #include <time.h>
  47.  
  48. static int RGB_attributes[] = {
  49.     GLX_RGBA,
  50.     GLX_RED_SIZE, 1,
  51.     GLX_GREEN_SIZE, 1,
  52.     GLX_BLUE_SIZE, 1,
  53.     None,
  54. };
  55.  
  56. static int CI_attributes[] = {
  57.     None,
  58. };
  59.  
  60. int rgb = 1;
  61.  
  62. #define PIXEL_CENTER(x) ((long) (x) + 0.5)
  63. #define SETCOLOR(x) (rgb ? glColor3fv(rgbMap[x]) : glIndexf(x))
  64.  
  65. enum {
  66.     BLACK = 0,
  67.     RED,
  68.     GREEN,
  69.     YELLOW,
  70.     BLUE,
  71.     MAGENTA,
  72.     CYAN,
  73.     WHITE
  74. };
  75.  
  76. static float rgbMap[8][3] = {
  77.     {0, 0, 0},
  78.     {1, 0, 0},
  79.     {0, 1, 0},
  80.     {1, 1, 0},
  81.     {0, 0, 1},
  82.     {1, 0, 1},
  83.     {0, 1, 1},
  84.     {1, 1, 1}
  85. };
  86.  
  87.  
  88. #define GAP 10
  89. #define ROWS 3
  90. #define COLS 4
  91.  
  92. static long W = COLS*100 + (COLS + 1)*GAP;
  93. static long H = ROWS*100 + (ROWS + 1)*GAP;
  94. static long boxW = 100;
  95. static long boxH = 100;
  96. static long drawBuffer = GL_FRONT;
  97. static int randomVertex = 0;
  98. static int clipped = 0;
  99. static int fastest2D = 0;
  100. static int xoffset, yoffset;
  101.  
  102. static void Viewport(long row, long column)
  103. {
  104.     long x, y;
  105.  
  106.     x = GAP + column * (boxW + GAP);
  107.     y = GAP + row * (boxH + GAP);
  108.  
  109.     glDrawBuffer(GL_FRONT);
  110.  
  111.     glEnable(GL_SCISSOR_TEST);
  112.     glScissor(x, y, boxW, boxH);
  113.  
  114.     glPushAttrib(GL_COLOR_BUFFER_BIT);
  115.     glColorMask(1, 1, 1, 1);
  116.     glIndexMask(~0);
  117.     glClear(GL_COLOR_BUFFER_BIT);
  118.     glPopAttrib();
  119.  
  120.     glMatrixMode(GL_PROJECTION);
  121.     glLoadIdentity();
  122.     xoffset = yoffset = 0;
  123.     if (clipped) {
  124.     glViewport(x+boxW/2, y+boxH/2, boxW/2, boxH/2);
  125.     glOrtho(0, boxW/2, 0, boxH/2, -1.0, 1.0);
  126.     } else {
  127.     if (fastest2D) {
  128.         xoffset = x + boxW/2;
  129.         yoffset = y + boxH/2;
  130.         glViewport(0, 0, W, H);
  131.         glOrtho(0, W, 0, H, -1, 1);
  132.     } else {
  133.         glViewport(x, y, boxW, boxH);
  134.         glOrtho(-boxW/2, boxW/2, -boxH/2, boxH/2, -1.0, 1.0);
  135.     }
  136.     }
  137.     glMatrixMode(GL_MODELVIEW);
  138.  
  139.     glDrawBuffer(drawBuffer);
  140. }
  141.  
  142. static void myVertex(float x, float y)
  143. {
  144.     if (fastest2D) {
  145.     x += xoffset;
  146.     y += yoffset;
  147.     }
  148.     if (randomVertex) {
  149.     switch(random() % 3) {
  150.       case 0:
  151.         glVertex2f(x,y);
  152.         break;
  153.       case 1:
  154.         glVertex3f(x,y,0);
  155.         break;
  156.       case 2:
  157.         glVertex4f(x,y,0,1);
  158.         break;
  159.     }
  160.     } else {
  161.     glVertex2f(x,y);
  162.     }
  163. }
  164.  
  165. static void Point(void)
  166. {
  167.     long i;
  168.  
  169.     SETCOLOR(WHITE);
  170.     glBegin(GL_POINTS);
  171.     myVertex(0, 0);
  172.     for (i = 1; i < 8; i++) {
  173.         long j = i * 2;
  174.         SETCOLOR(i);
  175.         myVertex(-j, -j);
  176.         myVertex(-j, 0);
  177.         myVertex(-j, j);
  178.         myVertex(0, j);
  179.         myVertex(j, j);
  180.         myVertex(j, 0);
  181.         myVertex(j, -j);
  182.         myVertex(0, -j);
  183.     }
  184.     glEnd();
  185. }
  186.  
  187. static void Lines(void)
  188. {
  189.     long i;
  190.  
  191.     glPushMatrix();
  192.     glTranslatef(-12, 0, 0);
  193.     for (i = 1; i < 8; i++) {
  194.     SETCOLOR(i);
  195.     glBegin(GL_LINES);
  196.         myVertex(-boxW/4, -boxH/4);
  197.         myVertex(boxW/4, boxH/4);
  198.     glEnd();
  199.     glTranslatef(4, 0, 0);
  200.     }
  201.     glPopMatrix();
  202.  
  203.     /*
  204.     ** Draw a single vertex line to make sure nothing bad happens
  205.     */
  206.     glBegin(GL_LINES);
  207.     myVertex(0, 0);
  208.     glEnd();
  209. }
  210.  
  211. static void LineStrip(void)
  212. {
  213.     glBegin(GL_LINE_STRIP);
  214.     SETCOLOR(RED);
  215.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
  216.     SETCOLOR(GREEN);
  217.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
  218.     SETCOLOR(BLUE);
  219.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
  220.     SETCOLOR(WHITE);
  221.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
  222.     glEnd();
  223.  
  224.     /*
  225.     ** Draw a single vertex line to make sure nothing bad happens
  226.     */
  227.     glBegin(GL_LINE_STRIP);
  228.     myVertex(0, 0);
  229.     glEnd();
  230. }
  231.  
  232. static void LineLoop(void)
  233. {
  234.     glBegin(GL_LINE_LOOP);
  235.     SETCOLOR(RED);
  236.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
  237.     SETCOLOR(GREEN);
  238.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
  239.     SETCOLOR(BLUE);
  240.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
  241.     SETCOLOR(WHITE);
  242.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
  243.     glEnd();
  244.  
  245.     /*
  246.     ** Draw a two vertex line with XOR on to make sure that only the
  247.     ** endpoints show.  Since each line segment is drawn half-open,
  248.     ** the endpoints will not be drawn twice, thus leaving the XOR of
  249.     ** white in the color buffer.  When using an RGB color buffer, use
  250.     ** the blend function to approximate the effects of the XOR.
  251.     */
  252.     glEnable(GL_LOGIC_OP);
  253.     glEnable(GL_BLEND);
  254.     glLogicOp(GL_XOR);
  255.     glBlendFunc(GL_ONE, GL_ONE);
  256.     SETCOLOR(MAGENTA);
  257.     /* this line is vertical */
  258.     glBegin(GL_LINE_LOOP);
  259.     myVertex(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(-boxH/8));
  260.     myVertex(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8));
  261.     glEnd();
  262.     /* this line is horizontal */
  263.     glBegin(GL_LINE_LOOP);
  264.     myVertex(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8+5));
  265.     myVertex(PIXEL_CENTER(boxW/8), PIXEL_CENTER(boxH/8+5));
  266.     glEnd();
  267.     glDisable(GL_LOGIC_OP);
  268.     glDisable(GL_BLEND);
  269.  
  270.     /*
  271.     ** Draw a point at the center of the area so that we can count pixels
  272.     ** if needed.
  273.     */
  274.     SETCOLOR(GREEN);
  275.     glBegin(GL_POINTS);
  276.     myVertex(0, 0);
  277.     glEnd();
  278.  
  279.     /*
  280.     ** Draw a single vertex line to make sure nothing bad happens
  281.     */
  282.     glBegin(GL_LINE_LOOP);
  283.     myVertex(0, 0);
  284.     glEnd();
  285. }
  286.  
  287. #define OPENGL_WIDTH    48
  288. #define OPENGL_HEIGHT    13
  289. static GLubyte OpenGL_bits[] = {
  290.    0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
  291.    0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01,
  292.    0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01, 
  293.    0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
  294.    0x3e, 0x8f, 0xb7, 0xf9, 0xfc, 0x01, 
  295.    0x63, 0xdb, 0xb0, 0x8d, 0x0d, 0x00,
  296.    0x63, 0xdb, 0xb7, 0x8d, 0x0d, 0x00, 
  297.    0x63, 0xdb, 0xb6, 0x8d, 0x0d, 0x00,
  298.    0x63, 0x8f, 0xf3, 0xcc, 0x0d, 0x00, 
  299.    0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0a,
  300.    0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0e, 
  301.    0x63, 0x00, 0x00, 0x8c, 0xed, 0x0e,
  302.    0x3e, 0x00, 0x00, 0xf8, 0x0c, 0x00, 
  303. };
  304.  
  305. static void Bitmap(void)
  306. {
  307.     static const long xOrigin = 0;
  308.     static const long yOrigin = 3;
  309.  
  310.     /*
  311.     ** Draw some lines showing the left and bottom edges of the bitmap.
  312.     ** The red line is the vertical left edge of the bitmap.  The blue
  313.     ** line is the horizontal bottom edge of the bitmap.  The yellow line
  314.     ** is the horizontal base line of the bitmap.  The green lines mark
  315.     ** where the rasterpos will translate to. Take into account the x
  316.     ** origin.
  317.     */
  318.     glBegin(GL_LINES);
  319.     SETCOLOR(GREEN);
  320.     myVertex(-boxW/2, 0);
  321.     myVertex(boxW/2, 0);
  322.     myVertex(0, -boxH/2);
  323.     myVertex(0, boxH/2);
  324.     SETCOLOR(RED);
  325.     myVertex(-xOrigin, -yOrigin);
  326.     myVertex(-xOrigin, -yOrigin+OPENGL_HEIGHT);
  327.     SETCOLOR(BLUE);
  328.     myVertex(-xOrigin, -yOrigin);
  329.     myVertex(-xOrigin+OPENGL_WIDTH, -yOrigin);
  330.     glEnd();
  331.  
  332.     SETCOLOR(GREEN);
  333.  
  334.     glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE);
  335.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  336.  
  337.     glRasterPos2i(xoffset, yoffset);
  338.     glBitmap(OPENGL_WIDTH, OPENGL_HEIGHT, xOrigin, yOrigin, 0.0, 0.0, 
  339.         OpenGL_bits);
  340. }
  341.  
  342. static void Triangles(void)
  343. {
  344.     glBegin(GL_TRIANGLES);
  345.     SETCOLOR(GREEN);
  346.     myVertex(-boxW/4, -boxH/4);
  347.     SETCOLOR(RED);
  348.     myVertex(-boxW/8, -boxH/16);
  349.     SETCOLOR(BLUE);
  350.     myVertex(boxW/8, -boxH/16);
  351.  
  352.     SETCOLOR(GREEN);
  353.     myVertex(-boxW/4, boxH/4);
  354.     SETCOLOR(RED);
  355.     myVertex(-boxW/8, boxH/16);
  356.     SETCOLOR(BLUE);
  357.     myVertex(boxW/8, boxH/16);
  358.     glEnd();
  359.  
  360.     /*
  361.     ** Generate a 2 vertex triangle that should draw nothing
  362.     */
  363.     glBegin(GL_TRIANGLES);
  364.     myVertex(0, 0);
  365.     myVertex(-100, 100);
  366.     glEnd();
  367. }
  368.  
  369. static void TriangleStrip(void)
  370. {
  371.     glBegin(GL_TRIANGLE_STRIP);
  372.     SETCOLOR(GREEN);
  373.     myVertex(-boxW/4, -boxH/4);
  374.     SETCOLOR(RED);
  375.     myVertex(-boxW/4, boxH/4);
  376.     SETCOLOR(BLUE);
  377.     myVertex(0, -boxH/4);
  378.     SETCOLOR(WHITE);
  379.     myVertex(0, boxH/4);
  380.     SETCOLOR(CYAN);
  381.     myVertex(boxW/4, -boxH/4);
  382.     SETCOLOR(YELLOW);
  383.     myVertex(boxW/4, boxH/4);
  384.     glEnd();
  385.  
  386.     /*
  387.     ** Generate a 2 vertex triangle strip that should draw nothing
  388.     */
  389.     glBegin(GL_TRIANGLE_STRIP);
  390.     myVertex(0, 0);
  391.     myVertex(-100, 100);
  392.     glEnd();
  393. }
  394.  
  395. static void TriangleFan(void)
  396. {
  397.     long x0, x1, x2, x3;
  398.     long y0, y1, y2, y3;
  399.     long vx[8][2];
  400.     long i;
  401.  
  402.     /*
  403.     ** Construct an 8 sided convex polygon that is almost an octahedron
  404.     */
  405.     y0 = -boxH/4;
  406.     y1 = y0 + boxH/2/3;
  407.     y2 = y1 + boxH/2/3;
  408.     y3 = boxH/4;
  409.     x0 = -boxW/4;
  410.     x1 = x0 + boxW/2/3;
  411.     x2 = x1 + boxW/2/3;
  412.     x3 = boxW/4;
  413.  
  414.     vx[0][0] = x0; vx[0][1] = y1;
  415.     vx[1][0] = x0; vx[1][1] = y2;
  416.     vx[2][0] = x1; vx[2][1] = y3;
  417.     vx[3][0] = x2; vx[3][1] = y3;
  418.     vx[4][0] = x3; vx[4][1] = y2;
  419.     vx[5][0] = x3; vx[5][1] = y1;
  420.     vx[6][0] = x2; vx[6][1] = y0;
  421.     vx[7][0] = x1; vx[7][1] = y0;
  422.  
  423.     /*
  424.     ** Draw the polygon, shaded.  This will draw the same shape that the
  425.     ** polygon test draws, except that when flat shaded it should draw
  426.     ** entirely white.  When smooth shaded it will shade differently
  427.     ** than the polygon test.
  428.     */
  429.     glBegin(GL_TRIANGLE_FAN);
  430.     SETCOLOR(WHITE);
  431.     myVertex(0, 0);
  432.     for (i = 0; i < 8; i++) {
  433.         SETCOLOR(7-i);
  434.         myVertex(vx[i][0], vx[i][1]);
  435.     }
  436.     glEnd();
  437.  
  438.     /*
  439.     ** Generate a 2 vertex triangle fan that should draw nothing
  440.     */
  441.     glBegin(GL_TRIANGLE_FAN);
  442.     myVertex(0, 0);
  443.     myVertex(-100, 100);
  444.     glEnd();
  445. }
  446.  
  447. static void Rect(void)
  448. {
  449.     SETCOLOR(GREEN);
  450.     glRecti(xoffset-boxW/4, yoffset-boxH/4, xoffset+boxW/4, yoffset+boxH/4);
  451. }
  452.  
  453. static void Polygon(void)
  454. {
  455.     long x0, x1, x2, x3;
  456.     long y0, y1, y2, y3;
  457.     long vx[8][2];
  458.     long i;
  459.  
  460.     /*
  461.     ** Construct an 8 sided convex polygon that is almost an octahedron
  462.     */
  463.     y0 = -boxH/4;
  464.     y1 = y0 + boxH/2/3;
  465.     y2 = y1 + boxH/2/3;
  466.     y3 = boxH/4;
  467.     x0 = -boxW/4;
  468.     x1 = x0 + boxW/2/3;
  469.     x2 = x1 + boxW/2/3;
  470.     x3 = boxW/4;
  471.  
  472.     vx[0][0] = x0; vx[0][1] = y1;
  473.     vx[1][0] = x0; vx[1][1] = y2;
  474.     vx[2][0] = x1; vx[2][1] = y3;
  475.     vx[3][0] = x2; vx[3][1] = y3;
  476.     vx[4][0] = x3; vx[4][1] = y2;
  477.     vx[5][0] = x3; vx[5][1] = y1;
  478.     vx[6][0] = x2; vx[6][1] = y0;
  479.     vx[7][0] = x1; vx[7][1] = y0;
  480.  
  481.     /*
  482.     ** Draw the polygon, shaded.
  483.     */
  484.     glBegin(GL_POLYGON);
  485.     for (i = 0; i < 8; i++) {
  486.         SETCOLOR(7-i);
  487.         myVertex(vx[i][0], vx[i][1]);
  488.     }
  489.     glEnd();
  490.  
  491.     /*
  492.     ** Generate a 2 vertex polygon that should draw nothing
  493.     */
  494.     glBegin(GL_POLYGON);
  495.     myVertex(0, 0);
  496.     myVertex(100, 100);
  497.     glEnd();
  498. }
  499.  
  500. static void Quads(void)
  501. {
  502.     glBegin(GL_QUADS);
  503.     SETCOLOR(GREEN);
  504.     myVertex(-boxW/4, -boxH/4);
  505.     SETCOLOR(RED);
  506.     myVertex(-boxW/8, -boxH/16);
  507.     SETCOLOR(BLUE);
  508.     myVertex(boxW/8, -boxH/16);
  509.     SETCOLOR(WHITE);
  510.     myVertex(boxW/4, -boxH/4);
  511.  
  512.     SETCOLOR(GREEN);
  513.     myVertex(-boxW/4, boxH/4);
  514.     SETCOLOR(RED);
  515.     myVertex(-boxW/8, boxH/16);
  516.     SETCOLOR(BLUE);
  517.     myVertex(boxW/8, boxH/16);
  518.     SETCOLOR(WHITE);
  519.     myVertex(boxW/4, boxH/4);
  520.     glEnd();
  521.  
  522.     /*
  523.     ** Generate a 3 vertex quad that should draw nothing
  524.     */
  525.     glBegin(GL_QUADS);
  526.     myVertex(0, 0);
  527.     myVertex(100, 100);
  528.     myVertex(-100, 100);
  529.     glEnd();
  530. }
  531.  
  532. static void QuadStrip(void)
  533. {
  534.     glBegin(GL_QUAD_STRIP);
  535.     SETCOLOR(GREEN);
  536.     myVertex(-boxW/4, -boxH/4);
  537.     SETCOLOR(RED);
  538.     myVertex(-boxW/4, boxH/4);
  539.     SETCOLOR(BLUE);
  540.     myVertex(0, -boxH/4);
  541.     SETCOLOR(WHITE);
  542.     myVertex(0, boxH/4);
  543.     SETCOLOR(CYAN);
  544.     myVertex(boxW/4, -boxH/4);
  545.     SETCOLOR(YELLOW);
  546.     myVertex(boxW/4, boxH/4);
  547.     glEnd();
  548.  
  549.     /*
  550.     ** Generate a 3 vertex quad strip that should draw nothing
  551.     */
  552.     glBegin(GL_QUAD_STRIP);
  553.     myVertex(0, 0);
  554.     myVertex(100, 100);
  555.     myVertex(-100, 100);
  556.     glEnd();
  557. }
  558.  
  559. static void RotateColorMask(void)
  560. {
  561.     static long rotation=0;
  562.     
  563.     rotation = (rotation + 1) & 0x3;
  564.     switch (rotation) {
  565.       case 0:
  566.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  567.     glIndexMask( 0xff );
  568.     break;
  569.       case 1:
  570.     /* mask off red */
  571.     glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
  572.     glIndexMask( 0xfe );
  573.     break;
  574.       case 2:
  575.     /* mask off green */
  576.     glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
  577.     glIndexMask( 0xfd );
  578.     break;
  579.       case 3:
  580.     /* mask off blue */
  581.     glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
  582.     glIndexMask( 0xfb );
  583.     break;
  584.     }
  585. }
  586.  
  587. static void DoTests(void)
  588. {
  589.     Viewport(0, 0); Point();
  590.     Viewport(0, 1); Lines();
  591.     Viewport(0, 2); LineStrip();
  592.     Viewport(0, 3); LineLoop();
  593.  
  594.     Viewport(1, 0); Bitmap();
  595.     Viewport(1, 1); TriangleFan();
  596.     Viewport(1, 2); Triangles();
  597.     Viewport(1, 3); TriangleStrip();
  598.  
  599.     Viewport(2, 0); Rect();
  600.     Viewport(2, 1); Polygon();
  601.     Viewport(2, 2); Quads();
  602.     Viewport(2, 3); QuadStrip();
  603.  
  604.     glFlush();
  605. }
  606.  
  607. static void Usage(void)
  608. {
  609.     printf("Usage: tprim [-c]\n");
  610.     printf("   -c:  Run in color index mode\n");
  611.     exit(-1);
  612. }
  613.  
  614. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  615. {
  616.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  617.     return GL_TRUE;
  618.     }
  619.     return GL_FALSE;
  620. }
  621.  
  622. int main(int argc, char** argv)
  623. {
  624.     XVisualInfo *vi;
  625.     Display *dpy;
  626.     Colormap cmap;
  627.     Window window;
  628.     XSetWindowAttributes swa;
  629.     GLXContext cx;
  630.     XEvent event;
  631.     GLboolean needDisplay;
  632.     XColor white;
  633.     char *geometry = NULL;
  634.     XSizeHints sizehints;
  635.     int i;
  636.  
  637.     srandom(time(NULL));
  638.     rgb = 1;
  639.     for (i = 1; i < argc; i++) {
  640.     if (!strcmp(argv[i], "-geometry")) {
  641.         i++;
  642.         geometry = argv[i];
  643.     } else if (argv[i][0] == '-') {
  644.             switch (argv[i][1]) {
  645.               case 'c':
  646.                 rgb = GL_FALSE;
  647.                 break;
  648.               default:
  649.                 Usage();
  650.             }
  651.         } else {
  652.             Usage();
  653.         }
  654.     }
  655.  
  656.     dpy = XOpenDisplay(0);
  657.     if (!dpy) {
  658.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  659.     return -1;
  660.     }
  661.  
  662.     vi = glXChooseVisual(dpy, DefaultScreen(dpy),
  663.              rgb ? RGB_attributes : CI_attributes);
  664.     if (!vi) {
  665.     fprintf(stderr, "No singlebuffered rgba visual on \"%s\"\n",
  666.         getenv("DISPLAY"));
  667.     return -1;
  668.     }
  669.  
  670.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  671.                rgb ? AllocNone : AllocAll);
  672.     if (rgb) {
  673.     white.red = ~0;
  674.     white.green = ~0;
  675.     white.blue = ~0;
  676.     XAllocColor(dpy, cmap, &white);
  677.     swa.background_pixel = white.pixel;
  678.     } else {
  679.     swa.background_pixel = 7;
  680.     }
  681.  
  682.     if (!rgb) {
  683.     XColor buf;
  684.     int i;
  685.  
  686.     buf.flags = DoRed | DoGreen | DoBlue;
  687.  
  688.     /* Init color map */
  689.     for (i=0; i<16; i++) {
  690.         buf.pixel = i;
  691.         buf.blue = (i & 4) ? 65535 : 0;
  692.         buf.green = (i & 2) ? 65535 : 0;
  693.         buf.red = (i & 1) ? 65535 : 0;
  694.         if (i > 8) {
  695.         buf.red /= 2;
  696.         buf.green /= 2;
  697.         buf.blue /= 2;
  698.         }
  699.         XStoreColor(dpy, cmap, &buf);
  700.     }
  701.     }
  702.  
  703.     sizehints.flags = PPosition | PSize;
  704.     sizehints.width = W;
  705.     sizehints.height = H;
  706.     sizehints.x = 10;
  707.     sizehints.y = 10;
  708.     if(geometry) {
  709.     int flags, x, y, width, height;
  710.  
  711.     flags = XParseGeometry(geometry, &x, &y,
  712.                    (unsigned int *)&width,
  713.                    (unsigned int *)&height);
  714.         if(WidthValue & flags) {
  715.         sizehints.flags |= USSize;
  716.         sizehints.width = width;
  717.         W = width;
  718.     }
  719.     if(HeightValue & flags) {
  720.         sizehints.flags |= USSize;
  721.         sizehints.height = height;
  722.         H = height;
  723.     }
  724.     if(XValue & flags) {
  725.         if(XNegative & flags)
  726.         x = DisplayWidth(dpy, DefaultScreen(dpy)) + x 
  727.             - sizehints.width;
  728.             sizehints.flags |= USPosition;
  729.         sizehints.x = x;
  730.     }
  731.     if(YValue & flags) {
  732.         if(YNegative & flags)
  733.         y = DisplayHeight(dpy, DefaultScreen(dpy)) + y 
  734.             - sizehints.height;
  735.             sizehints.flags |= USPosition;
  736.         sizehints.y = y;
  737.     }
  738.     }
  739.     swa.border_pixel = 0;
  740.     swa.background_pixel = white.pixel;
  741.     swa.colormap = cmap;
  742.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  743.     | KeyReleaseMask;
  744.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  745.                            sizehints.x, sizehints.y,
  746.                sizehints.width, sizehints.height,
  747.                0, vi->depth, InputOutput, vi->visual,
  748.                CWBackPixel|CWBorderPixel|CWColormap|CWEventMask,
  749.                &swa);
  750.     XSetStandardProperties(dpy, window, rgb ? "tprim RGB" : "tprim CI", "tprim",
  751.                            None, argv, argc, &sizehints);
  752.     XSetWMColormapWindows(dpy, window, &window, 1);
  753.     XMapWindow(dpy, window);
  754.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  755.  
  756.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  757.     if (!glXMakeCurrent(dpy, window, cx)) {
  758.     fprintf(stderr, "Can't make window current to context\n");
  759.     return -1;
  760.     }
  761.  
  762.     if (rgb) {
  763.     glClearColor(1, 1, 1, 1);
  764.     } else {
  765.     glClearIndex(7);
  766.     }
  767.     glClear(GL_COLOR_BUFFER_BIT);
  768.     if (rgb) {
  769.     glClearColor(0, 0, 0, 0);
  770.     } else {
  771.     glClearIndex(0);
  772.     }
  773.  
  774.     needDisplay = GL_TRUE;
  775.     for (;;) {
  776.     do {
  777.         XNextEvent(dpy, &event);
  778.         switch (event.type) {
  779.           case Expose:
  780.         needDisplay = GL_TRUE;
  781.         break;
  782.           case ConfigureNotify:
  783.         W = event.xconfigure.width;
  784.         H = event.xconfigure.height;
  785.         needDisplay = GL_TRUE;
  786.         break;
  787.           case KeyPress:
  788.         {
  789.             char buf[100];
  790.             int rv;
  791.             KeySym ks;
  792.  
  793.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  794.             switch (ks) {
  795.               case XK_F:
  796.               case XK_f:
  797.             glShadeModel(GL_FLAT);
  798.             needDisplay = GL_TRUE;
  799.             break;
  800.               case XK_S:
  801.               case XK_s:
  802.             glShadeModel(GL_SMOOTH);
  803.             needDisplay = GL_TRUE;
  804.             break;
  805.               case XK_P:
  806.               case XK_p:
  807.             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  808.             needDisplay = GL_TRUE;
  809.             break;
  810.               case XK_L:
  811.               case XK_l:
  812.             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  813.             needDisplay = GL_TRUE;
  814.             break;
  815.               case XK_C:
  816.               case XK_c:
  817.             RotateColorMask();
  818.             needDisplay = GL_TRUE;
  819.             break;
  820.               case XK_B:
  821.               case XK_b:
  822.             switch(drawBuffer) {
  823.               case GL_FRONT:
  824.                 drawBuffer = GL_NONE;
  825.                 printf("Drawing to GL_NONE.\n");
  826.                 break;
  827.               case GL_NONE:
  828.                 drawBuffer = GL_FRONT;
  829.                 printf("Drawing to GL_FRONT.\n");
  830.                 break;
  831.             }
  832.             needDisplay = GL_TRUE;
  833.             break;
  834.               case XK_R:
  835.               case XK_r:
  836.             randomVertex = 1-randomVertex;
  837.             needDisplay = GL_TRUE;
  838.             break;
  839.               case XK_Q:
  840.               case XK_q:
  841.             clipped = 1-clipped;
  842.             fastest2D = 0;
  843.             needDisplay = GL_TRUE;
  844.             break;
  845.               case XK_2:
  846.             fastest2D = 1-fastest2D;
  847.             clipped = 0;
  848.             needDisplay = GL_TRUE;
  849.             break;
  850.               case XK_Escape:
  851.             return 0;
  852.             }
  853.         }
  854.         break;
  855.         }
  856.     } while (XPending(dpy) != 0);
  857.  
  858.     if (needDisplay) {
  859.         needDisplay = GL_FALSE;
  860.         DoTests();
  861.     }
  862.     }
  863. }
  864.